/** Door_control_dll.cpp
 * dll to work with door controller
 * it controls actuator, relay to break modem power
 * and reads state of reeds
 * to compile
 * cd to
 *      ~/My_Designs/Door_control/Soft_PC/Door_control_gcc_win/Door_control_dll/Release
 * and run
 *      i586-mingw32msvc-g++ -universalg++ -O3 -Wall -c -fmessage-length=0 -omain_dll.o ../main_dll.cpp
 *      i586-mingw32msvc-g++ -universalg++ -shared -oDoor_control_dll.dll main_dll.o -Wl,--out-implib,main_dll.a
 *
 *
 *  Created on: 04.07.2012
 *     @Author: aska
 */

//TODO: Check port if open in functions
//#include <io.h>

#include "Door_control_dll.h"
//#define VERSION "1.1.1"
#define VERSION STRINGIZE(BUILD_MAJOR) "." STRINGIZE(BUILD_MINOR)
#define BUILD_MAJOR 1
#define BUILD_MINOR 4
char build_str[] = {BUILD_MAJOR + '0', '.', BUILD_MINOR + '0', '.', __DATE__[7], __DATE__[8], __DATE__[9], __DATE__[10], '\0'};
using namespace std;

door_control_device * ser_port_inst;

HINSTANCE dll_handle;

door_control_device::door_control_device() {
	strcpy(ser_port_name, "");
	baud = 19200;
	read_buff_after_writing = 1;
	tries_n = 3;
	inps_state_pres = 0;
	inps_state_prev = 0;
	lock_state_pres = 0;
	lock_state_prev = 0;
	d2xx_dll_is_loaded = 0;
	d2xx_opened = 0;
	ft_handle_opened = 0;
	serial_is_opened = 0;
	dev_interface_mode = 1;
	ft_LocId = 0;
	dbg_inps_r_counter = 0;
	ping_result = 0;
	ping_skipped = 0;
	ping_thread_command = no_command;
	ping_is_running = 0;
	ping_period_online = 1000;
	ping_period_offline = 2000;
	ping_delay_after_reset = 2000;
	//pinger pinger_inst;
	//door_control_device_inst = this;
	//ser_port_mutex = boost::interprocess::interprocess_mutex;
	//char str_path_to_exe[255];
	//strcpy(log_file_path, "C:/WINDOWS/sustem32/file.txt");
	//strcpy(log_file_path, "C:\\WINDOWS\\sustem32\\file.txt");
	GetModuleFileName(dll_handle, module_file_path, 255);
	//printf("str_path_to_exe %s\n", log_file_path);
	char * substr_occ;
	substr_occ = strrchr(module_file_path, '/');
	if (substr_occ == NULL)
		substr_occ = strrchr(module_file_path, '\\');
	if (substr_occ != NULL)
	{
		*(substr_occ + 1) = '\0';
		//printf("path for log file: %s\n", log_file_path);
	}
	else
	{
		module_file_path[0] = '\0';
		printf("path not found, use empty string as path for log file\n");
	}

	log_file_year_day_prev = 0;
	log_file_year_day_pres = 0;
	time_t rawtime;
	struct tm * timeinfo;
	time ( &rawtime );
	timeinfo = localtime ( &rawtime );
	log_file_year_day_prev = log_file_year_day_pres;
	//log_file_year_day_pres = timeinfo->tm_yday;
	log_file_year_day_pres = timeinfo->tm_mday;
	sprintf(log_file_name, "%sdoor_control_log_%04d_%02d_%02d.log", module_file_path, timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
	//printf("log file name: %s\n", log_file_name);
	log_file_ptr = fopen(log_file_name, "a+");
	log_add_str(const_cast<char*>("init resources object ready"));
	read_params();
	log_add_str(const_cast<char*>("read_params ready"));

}

int door_control_device::read_params()
{
	int ret_val = 0;
	//char ret_str[63];
	char buf_str[63];
	string ping_addr_str;
	boost::program_options::options_description desc_config_file("config file");
	desc_config_file.add_options()
			("help", "produce help message")
			("link.addr",
					boost::program_options::value<string>(& ping_addr_str)->default_value("127.0.0.1"), "set address to ping")
			("link.period_online",
					boost::program_options::value<int>(& ping_period_online)->default_value(1000), "ping period if online")
			("link.period_offline",
					boost::program_options::value<int>(& ping_period_offline)->default_value(2000), "ping period if offline")
			("link.delay_after_reset",
					boost::program_options::value<int>(& ping_delay_after_reset)->default_value(4000), "delay to ping after reset")
			("link.ping_timeout",
					boost::program_options::value<int>(& ping_timeout)->default_value(5000), "ping timeout")
			("link.to_start",
					boost::program_options::bool_switch(& ping_to_start)->default_value(false), "start link check if set")
			("todo", boost::program_options::value< vector<string> >()->multitoken()->zero_tokens(),
					"todo list\n"
					);
	;
    boost::program_options::variables_map vm;
	try
	{
		char config_file_name[63];
		sprintf(config_file_name, "%sdev_control_config.ini", module_file_path);
		cout << "read config file " << config_file_name << endl;
		std::ifstream settings_file( config_file_name );
		boost::program_options::store(boost::program_options::parse_config_file( settings_file , desc_config_file ), vm);
		cout << "read config file ready" << endl;
		// Вызвать функции уведомления (value_notifier() в данном случае).
		boost::program_options::notify(vm);
		settings_file.close();
	}
	catch (const boost::program_options::invalid_command_line_syntax &inv_syntax) {
		switch (inv_syntax.kind()) {
		case boost::program_options::invalid_syntax::missing_parameter:
			cout << "Missing argument for option '" << inv_syntax.tokens() << "'.\n";
			sprintf(buf_str, " read_config_err Missing argument for option %s",  inv_syntax.tokens().c_str());
			log_add_str(buf_str);
			break;
		default:
			cout << "Syntax error, kind " << int(inv_syntax.kind()) << "\n";
			sprintf(buf_str, " read_config_err Syntax error, kind %d", int(inv_syntax.kind()));
			log_add_str(buf_str);
			break;
		};
		ret_val = 2;
	}
	catch (const boost::program_options::unknown_option &unkn_opt) {
		cout << "Unknown option '" << unkn_opt.get_option_name() << "'\n";
		sprintf(buf_str, " read_config_err Syntax error, kind %s", unkn_opt.get_option_name());
		log_add_str(buf_str);
		ret_val = 2;
	}
	catch (std::exception& e)
	{
		std::cerr << "read config file exception: " << e.what() << std::endl;
		sprintf(buf_str, " read_config_err %s", e.what());
		log_add_str(buf_str);
		ret_val = 2;
	}
	cout << " ret_val " << ret_val << endl;

	cout << "read_config_file " << ret_val << endl;
	strcpy(ping_addr_char, ping_addr_str.c_str());
	if (ret_val == 0)
	{
		sprintf(buf_str, " ping_addr_char          %s", ping_addr_char);
		printf("%s\n", buf_str);
		log_add_str(buf_str);
		sprintf(buf_str, " ping_period_online      %d", ping_period_online);
		printf("%s\n", buf_str);
		log_add_str(buf_str);
		sprintf(buf_str, " ping_period_offline     %d", ping_period_offline);
		printf("%s\n", buf_str);
		log_add_str(buf_str);
		sprintf(buf_str, " ping_delay_after_reset  %d", ping_delay_after_reset);
		printf("%s\n", buf_str);
		log_add_str(buf_str);
		sprintf(buf_str, " ping_timeout            %d", ping_timeout);
		printf("%s\n", buf_str);
		log_add_str(buf_str);
		sprintf(buf_str, " ping_to_start           %d", ping_to_start);
		printf("%s\n", buf_str);
		log_add_str(buf_str);
	}
	return ret_val;
}

int door_control_device::log_add_str(char * log_str)
{
	int ret_val = 0;
	if (log_file_ptr != NULL)
	{
		char formatted_time[63];
		time_t rawtime;
		struct tm * timeinfo;
		time ( &rawtime );
		timeinfo = localtime ( &rawtime );
		log_file_year_day_prev = log_file_year_day_pres;
		//log_file_year_day_pres = timeinfo->tm_yday;
		log_file_year_day_pres = timeinfo->tm_mday;
		if (log_file_year_day_prev != log_file_year_day_pres)
		{
			//printf("next log file\n");
			sprintf(log_file_name, "%sdoor_control_log_%04d_%02d_%02d.log", module_file_path, timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
			//printf("new log file name: %s\n", log_file_name);
			fclose(log_file_ptr);
			log_file_ptr = fopen(log_file_name, "a+");
		}
		//strftime (formatted_time, 63, "%Y.%m.%d %X",timeinfo);
		strftime (formatted_time, 63, "%X",timeinfo);
		fprintf(log_file_ptr, "%s : %s\n", formatted_time, log_str);
		fflush(log_file_ptr);
		//printf(" log: %s", log_str);
	}
	return ret_val;
}


int door_control_device::set_read_buff_after_writing(int inp_val)
{
	read_buff_after_writing = inp_val;
	return 0;
}

int door_control_device::set_baud(int inp_baud)
{
	baud = inp_baud;
	dcb_curr.BaudRate = baud;
	return 0;
}
int door_control_device::get_baud()
{
	return baud;
}
int door_control_device::open_ser()
{
	int ret_val = 0;
	int res_var = 0;
	int err_code = 0;
	serial_is_opened = 0;
	char log_str[63];
	//printf(" open port %s\n", ser_port_name);
	hPort=CreateFile(
		ser_port_name, GENERIC_WRITE+GENERIC_READ, 0, NULL,
		OPEN_EXISTING, FILE_FLAG_OVERLAPPED*0, 0 );
	if (hPort == INVALID_HANDLE_VALUE)
	{
		ret_val = 1;
		err_code = GetLastError();
		sprintf(log_str, " ser_port::open CreateFile error GetLastError: %d", err_code);
		log_add_str(log_str);
	}
	else
	{
		GetCommState(hPort, &dcb_prev);
		dcb_curr = dcb_prev;
		dcb_curr.DCBlength = sizeof(DCB);
		dcb_curr.BaudRate = baud;
		dcb_curr.fBinary = TRUE;
		dcb_curr.fOutxCtsFlow = FALSE;
		dcb_curr.fOutxDsrFlow = FALSE;
		dcb_curr.fDtrControl = DTR_CONTROL_DISABLE;
		dcb_curr.fTXContinueOnXoff = TRUE;
		dcb_curr.fOutX = FALSE;
		dcb_curr.fInX = FALSE;
		dcb_curr.fDsrSensitivity = FALSE;
		dcb_curr.fNull = FALSE;
		dcb_curr.fRtsControl = RTS_CONTROL_DISABLE;
		dcb_curr.fAbortOnError = FALSE;
		dcb_curr.ByteSize = 8;
		dcb_curr.Parity = NOPARITY;
		dcb_curr.fParity = FALSE;
		dcb_curr.StopBits = ONESTOPBIT;
		dcb_curr.fNull = FALSE;
		dcb_curr.fAbortOnError = FALSE;

		if (SetCommState(hPort, &dcb_curr) == 0)
		{
			ret_val = 2;
			err_code = GetLastError();
			sprintf(log_str, " ser_port::open SetCommState error GetLastError: %d", err_code);
			log_add_str(log_str);
			CloseHandle(hPort);
		}
		else
		{
			GetCommTimeouts( hPort, &CommTimeOuts_prev);
			CommTimeOuts_curr = CommTimeOuts_prev;
			CommTimeOuts_curr.WriteTotalTimeoutMultiplier=2;
			CommTimeOuts_curr.WriteTotalTimeoutConstant=200;
			CommTimeOuts_curr.ReadIntervalTimeout=40;
			CommTimeOuts_curr.ReadTotalTimeoutMultiplier=2;
			CommTimeOuts_curr.ReadTotalTimeoutConstant=200;
			SetCommTimeouts( hPort, &CommTimeOuts_curr);
			ret_val = 0;
			/*
			CommTimeOuts.ReadIntervalTimeout= 10;
			CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
			// значений этих тайм – аутов вполне хватает для уверенного приема
			// даже на скорости 110 бод
			CommTimeOuts.ReadTotalTimeoutConstant = 100;
			// используется в данном случае как время ожидания посылки
			CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
			CommTimeOuts.WriteTotalTimeoutConstant = 0;
			SetCommTimeouts(handle, &CommTimeOuts); */
			serial_is_opened = 1;
		}
	}
	if ( serial_is_opened == 1 && read_buff_after_writing)
	{
		char buf_str[63];
		int ret_len = 0;
		Sleep(1000);
		read_buf(buf_str, &ret_len, 63);
	}
	if (serial_is_opened == 0)
		res_var = close_ser();
	return ret_val;
}

int door_control_device::open_d2xx_dll(void)
{
	//printf("open_d2xx_dll\n");
	int ret_val = 0;
	int func_counter = 0;
	int load_func_err = 0;
	char log_str[63];
	h_d2xx_dll = LoadLibrary("../../Door_control_dll/Release/ftd2xx.dll");
	if (!(h_d2xx_dll > (void*)HINSTANCE_ERROR))
		h_d2xx_dll = LoadLibrary("ftd2xx.dll");
	if (!(h_d2xx_dll > (void*)HINSTANCE_ERROR))
	{
		sprintf(log_str, " ser_port::open_d2xx unable LoadLibrary(""ftd2xx.dll"") error");
		printf("%s\n", log_str);
		log_add_str(log_str);
		ret_val = -1;
		d2xx_dll_is_loaded = 0;
	}
	else
	{
		printf("LoadLibrary(""ftd2xx.dll"") OK\n");
		d2xx_dll_is_loaded = 1;
	}
	if(h_d2xx_dll > (void*)HINSTANCE_ERROR)
	{
		func_counter++;
		if (! (FT_Open = (t_FT_Open)GetProcAddress(h_d2xx_dll, "FT_Open")))
		{
			printf("Error locating FT_Open function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_OpenEx = (t_FT_OpenEx)GetProcAddress(h_d2xx_dll, "FT_OpenEx")))
		{
			printf("Error locating FT_OpenEx function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_Close = (t_FT_Close)GetProcAddress(h_d2xx_dll, "FT_Close")))
		{
			printf("Error locating FT_Close function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_Purge = (t_FT_Purge)GetProcAddress(h_d2xx_dll, "FT_Purge")))
		{
			printf("Error locating FT_Purge function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_CreateDeviceInfoList = (t_FT_CreateDeviceInfoList)GetProcAddress(h_d2xx_dll, "FT_CreateDeviceInfoList")))
		{
			printf("Error locating FT_CreateDeviceInfoList function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_GetDriverVersion = (t_FT_GetDriverVersion)GetProcAddress(h_d2xx_dll, "FT_GetDriverVersion")))
		{
			printf("Error locating FT_GetDriverVersion function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_GetDeviceInfoList = (t_FT_GetDeviceInfoList)GetProcAddress(h_d2xx_dll, "FT_GetDeviceInfoList")))
		{
			printf("Error locating FT_GetDeviceInfoList function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_GetComPortNumber = (t_FT_GetComPortNumber)GetProcAddress(h_d2xx_dll, "FT_GetComPortNumber")))
		{
			printf("Error locating FT_GetComPortNumber function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_SetBaudRate = (t_FT_SetBaudRate)GetProcAddress(h_d2xx_dll, "FT_SetBaudRate")))
		{
			printf("Error locating FT_SetBaudRate function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_SetTimeouts = (t_FT_SetTimeouts)GetProcAddress(h_d2xx_dll, "FT_SetTimeouts")))
		{
			printf("Error locating FT_SetTimeouts function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_SetDataCharacteristics = (t_FT_SetDataCharacteristics)GetProcAddress(h_d2xx_dll, "FT_SetDataCharacteristics")))
		{
			printf("Error locating FT_SetDataCharacteristics function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_SetFlowControl = (t_FT_SetFlowControl)GetProcAddress(h_d2xx_dll, "FT_SetFlowControl")))
		{
			printf("Error locating FT_SetFlowControl function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_Read = (t_FT_Read)GetProcAddress(h_d2xx_dll, "FT_Read")))
		{
			printf("Error locating FT_Read function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_Write = (t_FT_Write)GetProcAddress(h_d2xx_dll, "FT_Write")))
		{
			printf("Error locating FT_Write function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_GetDriverVersion = (t_FT_GetDriverVersion)GetProcAddress(h_d2xx_dll, "FT_GetDriverVersion")))
		{
			printf("Error locating FT_GetDriverVersion function \n");
			load_func_err |= 0x01 << func_counter;
		}
		func_counter++;
		if (! (FT_GetLibraryVersion = (t_FT_GetLibraryVersion)GetProcAddress(h_d2xx_dll, "FT_GetLibraryVersion")))
		{
			printf("Error locating FT_GetLibraryVersion function \n");
			load_func_err |= 0x01 << func_counter;
		}

		if (! (FT_W32_GetLastError = (t_FT_W32_GetLastError)GetProcAddress(h_d2xx_dll, "FT_W32_GetLastError")))
		{
			printf("Error locating FT_W32_GetLastError function \n");
			load_func_err |= 0x01 << func_counter;
		}
		if (! (FT_CyclePort = (t_FT_CyclePort)GetProcAddress(h_d2xx_dll, "FT_CyclePort")))
		{
			printf("Error locating FT_CyclePort function \n");
			load_func_err |= 0x01 << func_counter;
		}

	}
	ret_val |= load_func_err;
	return ret_val;
}

int door_control_device::open_d2xx(void)
{
	//printf("open_d2xx\n");
	int ret_val = 0;
	int ret_res = 0;
	int i1 = 0;
	ret_res = open_d2xx_dll();
	int load_func_err = 0;
	int func_counter = 0;
	FT_HANDLE ft_handle_local;
	char * ser_port_name_upercase_pos = 0;
	DWORD numDevs;
	int ft_sel_index = -1;
	FT_DEVICE_LIST_INFO_NODE *p_FT_DEVICE_LIST_INFO_NODE;
	char ser_port_name_uppercase[15];
	int ser_port_no = -1;
	long ft_port_no = 0;
	char log_str[31];
	//printf("uppercase\n");
	//printf("ser_name %s.\n", ser_port_name);
	for (i1 = 0; i1 < strlen(ser_port_name); i1++)
	{
	    ser_port_name_uppercase[i1] = toupper(ser_port_name[i1]);
	}
	ser_port_name_uppercase[i1++] = 0;
	ser_port_name_upercase_pos = strstr(ser_port_name_uppercase, "COM");
	if (ser_port_name_upercase_pos < 0)
	{
		sprintf(log_str, " ser_port::open_d2xx incorrect serial name error");
		printf("%s\n", log_str);
		log_add_str(log_str);
		ret_val = 1;
		return ret_val;
	}
	else
	{
		//printf("ser_no_str %s.\n", ser_port_name_upercase_pos + 3);
	}
	sscanf(ser_port_name_upercase_pos + 3, "%d", &ser_port_no);
	printf("ser_no %d\n", ser_port_no);
	ft_status = FT_CreateDeviceInfoList(&numDevs);
	int local_numDevs = numDevs;
	if (ft_status == FT_OK)
	{
		printf("number of devices %d\n", numDevs);
	}
	else
	{
		sprintf(log_str, " ser_port::open_d2xx FT_CreateDeviceInfoList error : %d", ft_status);
		printf("%s\n", log_str);
		log_add_str(log_str);
		ret_val = 2;
		return ret_val;
	}
	p_FT_DEVICE_LIST_INFO_NODE = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs);
	ft_status = FT_GetDeviceInfoList(p_FT_DEVICE_LIST_INFO_NODE, &numDevs);

	for (int i = 0; i < local_numDevs; i++)
	{
		printf("Dev %d of %d:\n", i, numDevs);
		printf(" Flags=0x%x\n",p_FT_DEVICE_LIST_INFO_NODE[i].Flags);
		printf(" Type=0x%x\n",p_FT_DEVICE_LIST_INFO_NODE[i].Type);
		printf(" ID=0x%x\n",p_FT_DEVICE_LIST_INFO_NODE[i].ID);
		printf(" LocId=0x%x\n",p_FT_DEVICE_LIST_INFO_NODE[i].LocId);
		printf(" SerialNumber=%s\n",p_FT_DEVICE_LIST_INFO_NODE[i].SerialNumber);
		printf(" Description=%s\n",p_FT_DEVICE_LIST_INFO_NODE[i].Description);
		printf(" ftHandle=0x%x\n",p_FT_DEVICE_LIST_INFO_NODE[i].ftHandle);
		//ft_status = FT_Open(i, &ft_handle_local);
		int try_no = 0;
		int try_result = 1;
		while(try_no < 2 && try_result != 0)
		{
			ft_status = FT_Open(i, &ft_handle_local);
			sprintf(log_str, " ser_port::open_d2xx scan try No %d ft_status = %d\n", try_no, ft_status);
			printf("%s\n", log_str);
			log_add_str(log_str);
			if (ft_status == FT_OK)
			{
				try_result = 0;
			}
			else
			{
				FT_Close(&ft_handle_local);
				switch (try_no)
				{
				default:
					FT_CyclePort(ft_handle_local);
					break;
				}
			}
			try_no++;
		}
		printf("  FT_Open(%d, %d):%d\n", i, ft_handle_local, ft_status);
		if(ft_status == FT_OK)
		{
			ft_status = FT_GetComPortNumber(ft_handle_local, &ft_port_no);
			if (ft_status == FT_OK)
			{
				printf(" port=%d\n", ft_port_no);
				if (ser_port_no == ft_port_no)
				{
					printf(" * it is here");
					ft_handle = ft_handle_local;
					ft_sel_index = i;
					ft_LocId = p_FT_DEVICE_LIST_INFO_NODE[i].LocId;
					printf(" index %d loc %d\n", ft_sel_index, ft_LocId);
				}
			}
			else
			{
				sprintf(log_str, " ser_port::open_d2xx Unable FT_GetComPortNumber, error %d\n", ft_status);
				printf("%s\n", log_str);
				log_add_str(log_str);
				ret_val = 3;
				//return ret_val;
			}
			ft_status = FT_Close(ft_handle_local);
			if (ft_status == FT_OK){}
			else
			{
				sprintf(log_str, " ser_port::open_d2xx FT_Close error : %d", ft_status);
				printf("%s\n", log_str);
				log_add_str(log_str);
				ret_val = 2;
				//return ret_val;
			}
		}else
		{
			sprintf(log_str, " ser_port::open_d2xx Unable to open device %d ft_status = %d\n", i, ft_status);
			printf("%s\n", log_str);
			log_add_str(log_str);
			ret_res = FT_W32_GetLastError(ft_handle);
			sprintf(log_str, " ser_port::open_d2xx FT_W32_GetLastError %d", ret_res);
			printf("%s\n", log_str);
			log_add_str(log_str);
			ret_val = 2;
			//return ret_val;
		}
	}
	if (ft_sel_index >= 0)
	{
		printf("Open index %d\n", ft_sel_index);
		int try_no = 0;
		int try_result = 1;
		ft_status = FT_Open(ft_sel_index, &ft_handle);
		/*
		while(try_no < 3 && try_result != 0)
		{
			ft_status = FT_Open(ft_sel_index, &ft_handle);
			sprintf(log_str, " ser_port::open_d2xx try No %d ft_status = %d\n", try_no, ft_status);
			printf("%s\n", log_str);
			log_add_str(log_str);
			if (ft_status == FT_OK)
			{
				try_result = 0;
			}
			else
			{
				FT_Close(&ft_handle_local);
				switch (try_no)
				{
				default:
					FT_CyclePort(ft_handle);
					break;
				}
			}
			try_no++;
		}
		*/
		d2xx_opened = 1;
		if (ft_status == FT_OK)
		{
			//printf(" opened\n");
		}
		else
		{
			sprintf(log_str, " ser_port::open_d2xx FT_Open error : %d", ft_status);
			printf("%s\n", log_str);
			log_add_str(log_str);
			ret_val = 4;
			return ret_val;
		}
		if (ft_status == FT_OK)
		{
			ft_status |= FT_SetBaudRate(ft_handle, baud);
			ft_status |= FT_SetDataCharacteristics(ft_handle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
			ft_status |= FT_SetTimeouts(ft_handle, 400, 400);
			ft_status |= FT_SetFlowControl(ft_handle, FT_FLOW_NONE, 0x11, 0x13);
			if (ft_status == FT_OK)
			{
				printf(" set parameters OK\n");
				log_add_str(const_cast<char *>("FT set parameters OK"));
			}
			ft_handle_opened = 1;
			if ( ft_handle_opened == 1 && read_buff_after_writing)
			{
				char buf_str[63];
				int ret_len = 0;
				Sleep(1000);
				read_buf(buf_str, &ret_len, 63);
				read_buf(buf_str, &ret_len, 63);
			}

		}
		if (ft_status != FT_OK)
		{
			ret_res = FT_W32_GetLastError(ft_handle);
			sprintf(log_str, " ser_port::open_d2xx error %n", ret_res);
			printf("%s\n", log_str);
			log_add_str(log_str);
		}

	}
	else
	{
		sprintf(log_str, " ser_port::open_d2xx ft_sel_index < 0 error");
		printf("%s\n", log_str);
		log_add_str(log_str);
		ret_val = 5;
		ft_status = FT_Close(ft_handle);
		d2xx_opened = 0;
		return ret_val;
		
	}
	return ret_val;
}

int door_control_device::ft_get_driver_version(unsigned int * ft_driver_ver)
{
	char log_str[31];
	int ret_var = 0;
	DWORD dw_ft_driver_ver = 0;
	if (d2xx_opened == 1)
	{
		//ft_status = FT_GetDriverVersion(ft_handle, &dw_ft_driver_ver);
		ft_status = FT_GetDriverVersion(ft_handle, (DWORD*)(ft_driver_ver));
		//*ft_driver_ver = static_cast<unsigned int>(dw_ft_driver_ver);
		if (ft_status != FT_OK)
		{
			ret_var = - ft_status;
			sprintf(log_str, " ser_port::ft_get_driver_version error ft_status: %d", ft_status);
			log_add_str(log_str);
		}
		else
		{
			//printf("FT_GetDriverVersion %X %X\n", dw_ft_driver_ver, *ft_driver_ver);
		}
	}
	else
	{
		ret_var = 1;
	}
	return ret_var;
}

int door_control_device::ft_get_library_version(unsigned int * ft_lib_ver)
{
	char log_str[31];
	int ret_var = 0;
	DWORD dw_ft_lib_ver = 0;
	if (d2xx_opened == 1)
	{
		//ft_status = FT_GetDriverVersion(ft_handle, &dw_ft_driver_ver);
		ft_status = FT_GetLibraryVersion((DWORD*)(ft_lib_ver));
		//*ft_driver_ver = static_cast<unsigned int>(dw_ft_driver_ver);
		if (ft_status != FT_OK)
		{
			ret_var = - ft_status;
			sprintf(log_str, " ser_port::ft_get_library_version error ft_status: %d", ft_status);
			log_add_str(log_str);
		}
		else
		{
			//printf("FT_GetDriverVersion %X %X\n", dw_ft_driver_ver, *ft_driver_ver);
		}
	}
	else
	{
		ret_var = 1;
	}
	return ret_var;
}

int door_control_device::write_strz(char * buf)
{
	DWORD n_send = 0;
	DWORD i_send = 0;
	bool ret_write_file = true;
	int ret_val = 0;
	int res_var = 0;
	char put_char = 0;
	int err_code = 0;
	char log_str[63];
	int try_No = 0;
	do
	{
		try_No++;
		if (serial_is_opened == 1)
		{
			//put_char = '\n';
			//WriteFile(hPort, &put_char, 1, &i_send, NULL);
			//Sleep(50);
			//if ( !WriteFile(hPort, buf, strlen(buf), (DWORD*)(&n_send), NULL))
			for(unsigned int i1 = 0; i1 < strlen(buf) && ret_write_file; i1++)
			{
				ret_write_file = WriteFile(hPort, buf + i1, 1, &i_send, NULL);
				Sleep(50);
				n_send += i_send;
				//if (!ret_write_file) break;
			}
			if ( !ret_write_file)
			{
				ret_val = -1;
				err_code = GetLastError();
				sprintf(log_str, " ser_port::write_strz WriteFile error GetLastError: %d", err_code);
				log_add_str(log_str);
			}
			else
				ret_val = n_send;
				Sleep(200);
		}
		else
		{
			if (d2xx_opened == 1)
			{
				//printf("FT_Write %d: %s\n", strlen(buf), buf);
				ft_status = FT_Write(ft_handle, buf, strlen(buf), &n_send);
				//printf("sended result %d, n %d\n", ft_status, n_send);
				if (ft_status != FT_OK)
				{
					ret_val = - ft_status;
					err_code = FT_W32_GetLastError(ft_handle);
					sprintf(log_str, " ser_port::write_strz FT_Write error ft_status: %d GetLastError: %d", ft_status, err_code);
					log_add_str(log_str);
					res_var = conn_repair();
					sprintf(log_str, " ser_port::write_strz conn_repair: %d", res_var);
				}
				else
				{
					ret_val = n_send;
					Sleep(200);
				}
			}
		}
	}
	while(try_No < 2 && ret_val != 0);
	return ret_val;
}
int door_control_device::read_buf(char * buf, int * n_recv, int size)
{
	int ret_val = 0;
	int err_code = 0;
	char log_str[63];
	//printf("serial_is_opened %d ; d2xx_opened %d\n", serial_is_opened, d2xx_opened);
	if (serial_is_opened == 1)
	{
		if ( !ReadFile(hPort, buf, size, (DWORD*)n_recv, NULL))
		{
			ret_val = -1;
			err_code = GetLastError();
			sprintf(log_str, " ser_port::read_buf ReadFile error GetLastError: %d", err_code);
			printf("%s\n", log_str);
			log_add_str(log_str);
		}
		else
			ret_val = * n_recv;
	}
	else
	{
		if (d2xx_opened == 1)
		{
			//printf("next FT_Read\n");
			ft_status = FT_Read(ft_handle, buf, size, (DWORD*)n_recv);
			if (ft_status != FT_OK)
			{
				ret_val = -ft_status;
				sprintf(log_str, " ser_port::read_buf FT_Read error ft_status: %d", ft_status);
				printf("%s\n", log_str);
				log_add_str(log_str);
			}
			else
			{
				//printf("received %d:\n%s\n", *n_recv, buf);
				ret_val = * n_recv;
				//Sleep(200);
			}
		}
	}
	return ret_val;
}
int door_control_device::purge_buf(void)
{
	int ret_val = 0;
	int err_code = 0;
	char log_str[63];
	if (serial_is_opened == 1)
	{
		if(PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR) == 0)
		{
			err_code = GetLastError();
			sprintf(log_str, " ser_port::purge_buf PurgeComm error ft_status: %d", err_code);
			printf("%s\n", log_str);
			log_add_str(log_str);
			ret_val = err_code;
		}
	}
	if (d2xx_opened == 1)
	{
		ft_status = FT_Purge(ft_handle, FT_PURGE_RX | FT_PURGE_TX);
		if(ft_status != FT_OK)
		{
			sprintf(log_str, " ser_port::purge_buf PurgeComm error ft_status: %d", ft_status);
			printf("%s\n", log_str);
			log_add_str(log_str);
			ret_val = ft_status;
		}
	}
	return ret_val;
}
int door_control_device::conn_repair(void)
{
	int ret_val = 0;
	int ret_res = 0;
	//char buf_str[127];
	char log_str[127];
	int try_No = 0;
	sprintf(log_str, " door_control_device::conn_repair");
	printf("%s\n", log_str);
	log_add_str(log_str);
	do
	{
		try_No++;
		if (d2xx_opened == 1)
		{
			sprintf(log_str, " d2xx_opened == 1 try No %d", try_No);
			printf("%s\n", log_str);
			log_add_str(log_str);
			ret_res = FT_W32_GetLastError(ft_handle);
			sprintf(log_str, " door_control_device::conn_repair FT_W32_GetLastError %d", ret_res);
			printf("%s\n", log_str);
			log_add_str(log_str);
			//if (ret_res == 4)
			{
				ft_status = FT_Close(ft_handle);
				sprintf(log_str, "  FT_Close ft_status = %d", ft_status);
				printf("%s\n", log_str);
				log_add_str(log_str);
				//ret_res = ser_port_inst->open_d2xx();
				//ft_status = FT_OpenEx(ft_LocId, FT_OPEN_BY_LOCATION, &ft_handle);
				ret_res = open_d2xx();
				//sprintf(log_str, "  FT_OpenEx(location %d) ft_status = %d", ft_LocId, ft_status);
				sprintf(log_str, "  open_d2xx() ret_res = %d", ret_res);
				printf("%s\n", log_str);
				log_add_str(log_str);
				ret_val = ret_res;
			}
		}
	}
	while (try_No < 3 && ret_val != 0);
	return ret_val;
}
int door_control_device::set_brd_ver(char board_version)
{
	char buf_str[127];
	int ret_len = 0;
	int ret_val = 0;
	int return_val = 0;
	char *pos = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "set_brd_ver 0x%02X\n", board_version);
		//printf(" command: %s\n", buf_str);
		ret_val = write_strz(buf_str);
		//printf(" result: %d\n", ret_val);
		Sleep(200);
		if (ret_val == 0) return_val |= 1;
		//printf(" ser_port modem : %s", buf_str);
		//printf("  send %s, transmitted %d\n", cmd_str, ret_val);
		//if (read_buff_after_writing)
		//{
			read_buf(buf_str, &ret_len, 127);
			//printf(" read_buf: %d\n", ret_len);
			for (int i1 = 0; i1 < ret_len; i1++)
			{
				//printf("%c\n", buf_str[i1]);
			}
			//printf(" read_buf: %d - %s\n", ret_len, buf_str);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 15, "BRDVER");
			if (pos - buf_str < 0) return_val |= 4;
			//printf("read buffer\n");
			//char buf_str[63];
			//int ret_len = 0;
			//Sleep(1000);
			sprintf(buf_str, "get_brd_ver\n");
			ret_val = 1;
			ret_val = write_strz(buf_str);
			Sleep(100);
			read_buf(buf_str, &ret_len, 127);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 10, "BRDVER ");
			//printf("pos %s is %d\n", buf_str + 12, pos - buf_str);
			if (pos - buf_str < 0) return_val |= 4;
			//printf("hex_str %s\n", buf_str + 10 + 11);
			//printf("sw ack \n %s \n\n length %d\n", buf_str, strlen(buf_str));
			//strcpy(buf, buf_str + 8);
		//}
	}
	return return_val;
	//return 0;
}
int door_control_device::get_brd_ver(char * board_version)
{
	char buf_str[127];
	int ret_len = 0;
	int ret_val = 0;
	int return_val = 0;
	char *pos = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "get_brd_ver\n");
		ret_val = 1;
		ret_val = write_strz(buf_str);
		Sleep(100);
		if (ret_val == 0) return_val |= 1;
		//printf(" ser_port modem : %s", buf_str);
		//printf("  send %s, transmitted %d\n", cmd_str, ret_val);
		//if (read_buff_after_writing)
		//{
			//printf("read buffer\n");
			//char buf_str[63];
			//int ret_len = 0;
			//Sleep(1000);
			read_buf(buf_str, &ret_len, 127);
			/*for (int i1 = 0; i1 < ret_len; i1++)
				printf("%c\n", buf_str[i1]);*/
			//strcat(buf_str, "BRDVER 0x03\n");
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 10, "BRDVER ");
			//printf("pos %s is %d\n", buf_str + 12, pos - buf_str);
			if (pos - buf_str < 0) return_val |= 4;
			//printf("sw ack \n %s \n\n length %d\n", buf_str, strlen(buf_str));
			//printf("hex_str %s\n", buf_str + 10 + 11);
			sscanf(buf_str + 10 + 11, "%X", board_version);
			//strcpy(buf, buf_str + 10 + 7);
		//}
	}
	return return_val;
}
int door_control_device::set_ser_no(char * buf)
{
	char buf_str[127];
	int ret_len = 0;
	int ret_val = 0;
	int return_val = 0;
	char *pos = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "set_ser_no %s\n", buf);
		//printf(" -- command %s\n", buf_str);
		ret_val = write_strz(buf_str);
		Sleep(200);
		if (ret_val == 0) return_val |= 1;
		//printf(" ser_port modem : %s", buf_str);
		//printf("  send %s, transmitted %d\n", cmd_str, ret_val);
		//if (read_buff_after_writing)
		//{
			//printf("read buffer\n");
			//char buf_str[63];
			//int ret_len = 0;
			//Sleep(1000);
			read_buf(buf_str, &ret_len, 127);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 15, "SERNO ");
			//printf("pos %s is %d\n", buf_str + 12, pos - buf_str);
			if (pos - buf_str < 0) return_val |= 4;
			//printf("sw ack \n %s \n\n length %d\n", buf_str, strlen(buf_str));
			//strcpy(buf, buf_str + 8);
		//}
	}
	return return_val;
}
int door_control_device::get_ser_no(char * buf)
{
	char buf_str[127];
	char log_str[63];
	int ret_len = 0;
	int ret_val = 0;
	int return_val = 0;
	char *pos = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		purge_buf();
		sprintf(buf_str, "get_ser_no\n");
		ret_val = write_strz(buf_str);
		Sleep(200);
		if (ret_val == 0) return_val |= 1;
		sprintf(log_str, " ser_port::get_ser_no write_strz: %d", ret_val);
		printf("%s\n", log_str);
		log_add_str(log_str);
		//printf(" ser_port modem : %s", buf_str);
		//printf("  send %s, transmitted %d\n", cmd_str, ret_val);
		//if (read_buff_after_writing)
		//{
			//printf("read buffer\n");
			//char buf_str[63];
			//int ret_len = 0;
			//Sleep(1000);
			read_buf(buf_str, &ret_len, 127);
			sprintf(log_str, " ser_port::get_ser_no read_buf len: %d", ret_len);
			printf("%s\n", log_str);
			for (int i1 = 0; i1 < ret_len; i1++)
				printf(" %d : %c \n", i1, buf_str[i1]);
			log_add_str(log_str);
			sprintf(log_str, " ser_port::get_ser_no read_buf: %s", buf_str);
			printf("%s\n", log_str);
			log_add_str(log_str);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 10, "SERNO ");
			printf("pos %s is %d\n", buf_str + 11, pos - buf_str);
			printf("pos + 6 %s\n", pos + 6);
			if (pos - buf_str < 0) return_val |= 4;
			printf("sw ack \n %s \n\n length %d\n", buf_str, strlen(buf_str));
			//strcpy(buf, buf_str + 10 + 7);
			strcpy(buf, pos + 6);
			sprintf(log_str, " ser_port::get_ser_no output buf: %s", buf);
			printf("%s\n", log_str);
			log_add_str(log_str);
			sprintf(log_str, " ser_port::get_ser_no return_val: %d", return_val);
			printf("%s\n", log_str);
			log_add_str(log_str);
		//}
	}
	return return_val;
}
int door_control_device::get_fwv(char * buf)
{
	char buf_str[127];
	int ret_len = 0;
	int ret_val = 0;
	int return_val = 0;
	char *pos = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "get_fwv\n");
		ret_val = write_strz(buf_str);
		Sleep(200);
		if (ret_val == 0) return_val |= 1;
		//printf(" ser_port modem : %s", buf_str);
		//printf("  send %s, transmitted %d\n", cmd_str, ret_val);
		//if (read_buff_after_writing)
		//{
			//printf("read buffer\n");
			//char buf_str[63];
			//int ret_len = 0;
			//Sleep(1000);
			read_buf(buf_str, &ret_len, 127);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 8, "fw ");
			//printf("pos %s is %d\n", buf_str + 12, pos - buf_str);
			if (pos - buf_str < 0) return_val |= 4;
			//printf("sw ack \n %s \n\n length %d\n", buf_str, strlen(buf_str));
			strcpy(buf, buf_str + 8);
		//}
	}
	return 0;
}
int door_control_device::led_set(int led_No, int led_state)
{
	char buf_str[63];
	//int ret_len = 0;
	int ret_val = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "led%d%c\n", led_No, (led_state==0)?'c':'s');
		ret_val = write_strz(buf_str);
		if (read_buff_after_writing)
		{
			char buf_str[63];
			int ret_len = 0;
			read_buf(buf_str, &ret_len, 63);
		}
	}
	return 0;
}
int door_control_device::get_sum(int a, int b, int * sum)
{
	*sum = a + b;
	return *sum;
}

int door_control_device::lock_set(int state)
{
	char buf_str[63];
	int ret_val = 0;
	int return_val = 0;
	char log_str[63];
	char* pos;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "lock %c", (state==0)?'c':'o');
		//TODO: try to fix warning: deprecated conversion from string constant to ‘char*’
		ret_val = (state != 0) ? write_strz(const_cast<char*>("lock_open\n")) : write_strz(const_cast<char*>("lock_close\n"));
		if (read_buff_after_writing)
		{
			char buf_str[63];
			int ret_len = 0;
			ret_val = read_buf(buf_str, &ret_len, 63);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + ((state != 0) ? 10 : 11), "lock_");
			if (pos - buf_str < 0)
			{
				sprintf(log_str, " ser_port::lock_set read_buf error: lock_ not found");
				printf("%s\n", log_str);
				log_add_str(log_str);
				sprintf(log_str, " ser_port::lock_set read_buf received %d bytes : %s", ret_len, buf_str);
				printf("%s\n", log_str);
				log_add_str(log_str);
				return_val |= 4;
			}
		}
	}
	return_val = (ret_val > 0) ? 0 : 1;;
	return 0;
}

int door_control_device::relay_4_set(int state)
{
	char buf_str[63];
	int ret_val = 0;
	int return_val = 0;
	char log_str[63];
	char* pos;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "relay_4 %c", (state==0)?'c':'o');
		//TODO: try to fix warning: deprecated conversion from string constant to ‘char*’
		ret_val = (state != 0) ? write_strz(const_cast<char*>("rel4s\n")) : write_strz(const_cast<char*>("rel4c\n"));
		if (read_buff_after_writing)
		{
			char buf_str[63];
			int ret_len = 0;
			ret_val = read_buf(buf_str, &ret_len, 63);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 6, "rel4");
			if (pos - buf_str < 0)
			{
				sprintf(log_str, " ser_port::door_control_relay_4_set read_buf error: rel4 not found");
				printf("%s\n", log_str);
				log_add_str(log_str);
				sprintf(log_str, " ser_port::door_control_relay_4_set read_buf received %d bytes : %s", ret_len, buf_str);
				printf("%s\n", log_str);
				log_add_str(log_str);
				return_val |= 4;
			}
		}
	}
	return_val = (ret_val > 0) ? 0 : 1;;
	return 0;
}

int door_control_device::modem_reset()
{
	char buf_str[63];
	int ret_val = 0;
	int return_val = 0;
	char *pos = 0;
	char log_str[63];
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		sprintf(buf_str, "modem_reset\n");//12 bytes with \n
		ret_val = write_strz(buf_str);
		if (ret_val == 0) return_val |= 1;
		if (read_buff_after_writing)
		{
			char buf_str[63];
			int ret_len = 0;
			read_buf(buf_str, &ret_len, 63);
			if (ret_len == 0) return_val |= 2;
			pos = strstr(buf_str + 12, "modem_reset");
			if (pos - buf_str < 0)
			{
				sprintf(log_str, " ser_port::modem_reset read_buf error: modem_reset not found");
				printf("%s\n", log_str);
				log_add_str(log_str);
				sprintf(log_str, " ser_port::modem_reset read_buf received %d bytes : %s", ret_len, buf_str);
				printf("%s\n", log_str);
				log_add_str(log_str);
				return_val |= 4;
			}
		}
	}
	return 0;
}

int door_control_device::ping_addr(char * ping_addr, int * ping_result)
{
	int ret_val = 0;
	//std::cout << "check_internet start " << endl;
	try
	{
		#if !defined(BOOST_WINDOWS)
			std::cerr << "(You may need to run this program as root.)" << std::endl;
		#endif
		*ping_result = 1;
		ret_val = *ping_result;
	}
	catch (std::exception& e)
	{
		std::cerr << "check_internet Exception: " << e.what() << std::endl;
		ret_val = 2;
	}
	return ret_val;
}

int door_control_device::ping_proc_work()
{
	ping_is_running = 1;
	int iter_counter = 0;
	int ret_val = 0;
	int res_val = 0;
	int dev_is_ready_counter = 0;
	//int * ping_result;
	char buf_str[31];
	cout << "ping_proc_work" << endl;
	sprintf(buf_str, "ping start");
	log_add_str(buf_str);
	ping_storage ping_storage_inst;
	ping_storage_inst.set_addr(ping_addr_char);
	ping_storage_inst.set_timeout(ping_timeout);
	while (ping_thread_command != quit)
	{
		iter_counter++;
		std::cout << "iter " << iter_counter << " " << " addr " << ping_addr_char << " timeout " << ping_timeout << endl;
		ping_storage_inst.run_once();
		std::cout << " result " << ping_storage_inst.ping_result_ << endl;
		if (ping_storage_inst.ping_result_ != 0)
		{
			sprintf(buf_str, "ping no response");
			log_add_str(buf_str);
			cout << buf_str << endl;
			if (serial_is_opened == 1 || ft_handle_opened == 1)
			{
				res_val = modem_reset();
				sprintf(buf_str, "modem reset %d", res_val);
				log_add_str(buf_str);
				cout << buf_str << endl;
			}
			Sleep(ping_delay_after_reset);
		}
		Sleep(ping_period_online);
	}
	ping_is_running = 0;
	sprintf(buf_str, "ping stop");
	log_add_str(buf_str);
	return ret_val;
}
void door_control_device::ping_thread()
{
	long tid;
	tid = 15;
	ser_port_inst->ping_proc_work();
}

int door_control_device::ping_ctrl(int set_state)
{
	int ret_val = 0;
	if (set_state == 1)
	{
		boost::thread make_thread(&ping_thread);
		//make_thread.join();
	}
	if (set_state == 0)
	{
		ping_thread_command = quit;
	}

	return ret_val;
}

int door_control_device::inps_get()
{
	char buf_str[63];
	int ret_len = 0;
	int ret_len_2 = 0;
	int ret_val = 0;
	int return_val = 0xF0;
	int count_try = 0;
	int result_ready = 0;;
	int pos_end_str = 0;
	char log_str[63];
	dbg_inps_r_counter++;
	//int dbg_inps_r_No = dbg_inps_r_counter;
	//sprintf(buf_str, "inps_get No %04d : start", dbg_inps_r_No);
	//log_add_str(buf_str);
	unsigned char ret_char = 0;
	char *pos = 0;
	{
		boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> lock(ser_port_mutex);
		while(result_ready == 0 && count_try < 3)
		{
			if (count_try > 0) purge_buf();// PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
			sprintf(buf_str, "inps_r\n");
			ret_val = write_strz(buf_str);
			if (ret_val <= 0) return_val = 0xA0;
			else
			{
				ret_len_2 = read_buf(buf_str, &ret_len, 63);
				//log_add_str("inps_get read_buf:");
				//log_add_str(buf_str);
				pos_end_str = 0;
				return_val = 0xB0;
				while(pos_end_str < ret_len && result_ready == 0)
				{
					pos = strstr(buf_str + pos_end_str, "inps_ack");
					if (pos > 0)
					{
						ret_char = pos[9];
						return_val = (ret_char > '9') ? (ret_char - 0x37) : (ret_char - 0x30);
						result_ready = 1;
					}
					else
					{
						return_val = 0xC0;
					}
					pos_end_str = pos_end_str + strlen(buf_str + pos_end_str) + 1;
				}
				if (return_val == 0xC0)
				{
					sprintf(log_str, " ser_port::inps_get read_buf error: inps_ack not found");
					printf("%s\n", log_str);
					log_add_str(log_str);
					sprintf(log_str, " ser_port::inps_get read_buf received %d bytes : %s", ret_len, buf_str);
					printf("%s\n", log_str);
					log_add_str(log_str);
				}
			}
			count_try++;
		}
	}
	inps_state_prev = inps_state_pres;
	inps_state_pres = return_val;
	//sprintf(buf_str, "inps_get No %04d : end", dbg_inps_r_No);
	//log_add_str(buf_str);
	return return_val;// buf_str[];
}
int door_control_device::close_ser()
{
	int err_code = 0;
	int ret_val = 0;
	char log_str[63];
	//serial_is_opened = 0;
	if (SetCommState(hPort, &dcb_prev) == 0)
	{
		ret_val = 2;
		err_code = GetLastError();
		sprintf(log_str, " ser_port::close SetCommState error GetLastError: %d", err_code);
		log_add_str(log_str);
	}
	if (SetCommTimeouts(hPort, &CommTimeOuts_prev) == 0)
	{
		ret_val = 3;
		err_code = GetLastError();
		sprintf(log_str, " ser_port::close SetCommTimeouts error GetLastError: %d", err_code);
		log_add_str(log_str);
	}
	if (CloseHandle(hPort) == 0)
	{
		ret_val = 4;
		err_code = GetLastError();
		sprintf(log_str, " ser_port::close CloseHandle error GetLastError: %d", err_code);
		log_add_str(log_str);
	}
	return ret_val;
}
int door_control_device::close()
{
	int ret_val = 0;
	int res_var = 0;
	//int err_code = 0;
	char log_str[63];
	if (serial_is_opened == 1 || true)
	{
		res_var = close_ser();
		sprintf(log_str, " ser_port::close close_ser : %d", (res_var));
		printf("%s", log_str);
		log_add_str(log_str);
		ret_val = res_var;
		serial_is_opened = 0;
	}
	if(ft_handle_opened == 1 || true)
	{
		ft_status = FT_Close(ft_handle);
		sprintf(log_str, " ser_port::close FT_Close : %d", (ft_status));
		printf("%s", log_str);
		log_add_str(log_str);
		if (ft_status == FT_OK){}
		else
		{
			sprintf(log_str, " ser_port::close FT_Close error : %d", (ft_status));
			printf("%s", log_str);
			log_add_str(log_str);
		}
		ft_handle_opened = 0;
	}
	if(d2xx_dll_is_loaded == 1 || true)
	{
		FreeLibrary(h_d2xx_dll);
		d2xx_dll_is_loaded = 0;
	}
	return 0;
}
door_control_device::~door_control_device() {
	// TODO Auto-generated destructor stub
	log_add_str(const_cast<char*>("free resources ~object"));
	close();
	fclose(log_file_ptr);
	//close();
}
__declspec(dllexport) BOOL WINAPI __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		/* Code path executed when DLL is loaded into a process's address space. */
		//printf("DLL_PROCESS_ATTACH\n");
		dll_handle = hinstDLL;
		break;
	case DLL_THREAD_ATTACH:
		/* Code path executed when a new thread is created within the process. */
		//printf("DLL_THREAD_ATTACH\n");
		break;
	case DLL_THREAD_DETACH:
		/* Code path executed when a thread within the process has exited *cleanly*. */
		//printf("DLL_THREAD_DETACH\n");
		break;
	case DLL_PROCESS_DETACH:
		//printf("DLL_PROCESS_DETACH\n");
		/* Code path executed when DLL is unloaded from a process's address space. */
		break;
	}
	return TRUE;
}

__declspec(dllexport) int __stdcall door_control_init(void)
{
	ser_port_inst = new door_control_device();
	char ret_str[63];
	int build_year = 0;
	int build_month = 0;
	int build_day = 0;
	int build_hour = 0;
	int build_min = 0;
	char build_month_str[4];
	char version_str[15];
	sscanf(__DATE__, "%s %d %d", build_month_str, &build_day, &build_year);
	//strncpy(build_month_str, __DATE__, 3);
	if (!strcmp(build_month_str, "Jan"))
		build_month = 1;
	if (!strcmp(build_month_str, "Feb"))
		build_month = 2;
	if (!strcmp(build_month_str, "Mar"))
		build_month = 3;
	if (!strcmp(build_month_str, "Apr"))
		build_month = 4;
	if (!strcmp(build_month_str, "May"))
		build_month = 5;
	if (!strcmp(build_month_str, "Jun"))
		build_month = 6;
	if (!strcmp(build_month_str, "Jul"))
		build_month = 7;
	if (!strcmp(build_month_str, "Aug"))
		build_month = 8;
	if (!strcmp(build_month_str, "Sep"))
		build_month = 9;
	if (!strcmp(build_month_str, "Oct"))
		build_month = 10;
	if (!strcmp(build_month_str, "Nov"))
		build_month = 11;
	if (!strcmp(build_month_str, "Dec"))
		build_month = 12;
	sscanf(__TIME__, "%d:%d", &build_hour, &build_min);
	sprintf(version_str, "%04d%02d%02d%02d%02d", build_year, build_month, build_day, build_hour, build_min);

	sprintf(ret_str, "-> door_control_init, dll version %s", version_str);
	ser_port_inst->log_add_str(ret_str);
	if (ser_port_inst != 0)
	{
		ser_port_inst->log_add_str(const_cast<char*>("<- OK"));
		return 0;
	}
	else
	{
		ser_port_inst->log_add_str(const_cast<char*>("<- Failed"));
		return 1;
	}
}
__declspec(dllexport) int __stdcall door_control_finish(void)
{
	ser_port_inst->log_add_str(const_cast<char*>("-- door_control_finish"));
	ser_port_inst->~door_control_device();
	return 0;
}
__declspec(dllexport) int __stdcall door_control_dev_if_mode(int mode)
{
	int ret_val = 0;
	if (mode >= 1 && mode <= 2)
	{
		ser_port_inst->dev_interface_mode = mode;
		ret_val = 0;
	}
	else
		ret_val = 1;
	return ret_val;
}
__declspec(dllexport) int __stdcall door_control_ser_open(void)
{
	int ret_var = ser_port_inst->open_ser();
	char ret_str[63];
	sprintf(ret_str, "-  door_control_ser_open %d", ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_dev_open(void)
{
	int ret_var = 0;
	//char fw_str[127];
	//int buf_len;
	char ret_str[63];
	char * pos_str;
	switch (ser_port_inst->dev_interface_mode)
	{
		case 1:
			ret_var = ser_port_inst->open_ser();
			break;
		case 2:
			ret_var = ser_port_inst->open_d2xx();
			break;
		default:
			ret_var = 7;
			sprintf(ret_str, "-  door_control_dev_open incorrect interface mode error");
			printf("%s\n", ret_str);
			ser_port_inst->log_add_str(ret_str);
			break;
	}			
	if (ret_var == 0)
	{
		ret_var = ser_port_inst->get_fwv(ser_port_inst->fwv_str) << 4;
		//strcpy(fwv_str, );
		if (ret_var == 0)
		{
			pos_str = strstr(ser_port_inst->fwv_str, "fw @type door_control");
			if ((pos_str - ser_port_inst->fwv_str) < 0)
			{
				printf(" get str:\n%s\n", ser_port_inst->fwv_str);
				ret_var = 3;
			}
		}
	}
	door_control_lock_set(0);
	sprintf(ret_str, "-  door_control_dev_open mode %d result %d", ser_port_inst->dev_interface_mode, ret_var);
	ser_port_inst->log_add_str(ret_str);
	if (ser_port_inst->ping_to_start)
	{
		sprintf(ret_str, "-  start ping");
		printf("%s\n", ret_str);
		ser_port_inst->log_add_str(ret_str);
		ping_start();
	}
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_ft_get_driver_version(unsigned int* ft_driver_ver)
{
	int ret_var = 0;
	ret_var = ser_port_inst->ft_get_driver_version(ft_driver_ver);
	//printf("door_control_ft_get_driver_version %X %X\n", ft_driver_ver, *ft_driver_ver);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_ft_get_library_version(unsigned int* ft_lib_ver)
{
	int ret_var = 0;
	ret_var = ser_port_inst->ft_get_library_version(ft_lib_ver);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_set_brd_ver(char buf)
{
	int ret_var = 0;
	ret_var = ser_port_inst->set_brd_ver(buf);
	char ret_str[63];
	sprintf(ret_str, "-  door_control_set_brd_ver %d", ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_get_brd_ver(char * buf)
{
	//char board_version;
	int ret_var = 0;
	//board_version = 0;
	ret_var = ser_port_inst->get_brd_ver(buf);
	char ret_str[63];
	sprintf(ret_str, "-  door_control_get_brd_ver %d", ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_set_ser_no(char * buf)
{
	int ret_var = 0;
	ret_var = ser_port_inst->set_ser_no(buf);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_get_ser_no(char * buf, int buf_len)
{
	char ser_no_str[127];
	int ret_var = 0;
	strcpy(ser_no_str, "no ser_no");
	ret_var = ser_port_inst->get_ser_no(ser_no_str);
	strncpy(buf, ser_no_str, min(127, buf_len));
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_get_fwv(char * buf, int buf_len)
{
	char fw_str[127];
	int ret_var = 0;
	strcpy(fw_str, "no fw");
	ret_var = ser_port_inst->get_fwv(fw_str);
	strncpy(buf, fw_str, min(127, buf_len));
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_ser_close(void)
{
	int ret_var = ser_port_inst->close();
	char ret_str[63];
	sprintf(ret_str, "-  door_control_ser_close %d", ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_ser_set_name(const char *s)
{
	strcpy(ser_port_inst->ser_port_name, s);
	char ret_str[63];
	sprintf(ret_str, "-  door_control_ser_set_name %s", ser_port_inst->ser_port_name);
	ser_port_inst->log_add_str(ret_str);
	return 0;
}
__declspec(dllexport) int __stdcall door_control_ser_set_num(int port_no)
{
	char port_name[12];
	sprintf(port_name, "//./COM%d", port_no);
	strcpy(ser_port_inst->ser_port_name, port_name);
	char ret_str[63];
	sprintf(ret_str, "-  door_control_ser_set_name %s", ser_port_inst->ser_port_name);
	ser_port_inst->log_add_str(ret_str);
	return 0;
}
__declspec(dllexport) int __stdcall door_control_ser_set_baud(int baud)
{
	ser_port_inst->set_baud(baud);
	return 0;
}
__declspec(dllexport) int __stdcall door_control_ser_get_baud(void)
{
	return ser_port_inst->get_baud();
}
__declspec(dllexport) int __stdcall door_control_ser_read_buf(char * buf, int * n_recv, int size)
{
	return ser_port_inst->read_buf(buf, n_recv, size);
}
__declspec(dllexport) int __stdcall door_control_leds_set(int led_No, int led_state)
{
	return ser_port_inst->led_set(led_No, led_state);
}
__declspec(dllexport) int __stdcall door_control_get_sum(int a, int b, int * sum)
{
	return ser_port_inst->get_sum(a, b, sum);
}
__declspec(dllexport) int __stdcall door_control_lock_set(int state)
{
	int ret_var = 0;
	int ret_var_2 = 0;
	if (ser_port_inst->lock_state_prev == state)
	{
		ret_var = ser_port_inst->lock_set((state != 0) ? 0 : 1);
		Sleep(100);
	}
	ret_var = ser_port_inst->lock_set(state);
	ser_port_inst->lock_state_prev = state;
	char ret_str[63];
	sprintf(ret_str, "-  door_control_lock_set(%d) %d", state, ret_var);
	ser_port_inst->log_add_str(ret_str);
	ret_var_2 = ser_port_inst->relay_4_set((state != 0) ? 0 : 1);
	sprintf(ret_str, "-  door_control_relay_4_set(%d) %d", state, ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_inps_get(void)
{
	int ret_var = ser_port_inst->inps_get();
	char ret_str[127];
	if (ser_port_inst->inps_state_pres != ser_port_inst->inps_state_prev)
	{
		sprintf(ret_str, "-  door_control_inps_get %2d: active 0 - man_lock_%s; lock_%s; door_%s; spare %d", ret_var, ((ret_var >> 0) & 0x01 == 1)?"closed 1":"opened 0", ((ret_var >> 1) & 0x01)?"closed 1":"opened 0", ((ret_var >> 2) & 0x01 == 1)?"opened 1":"closed 0", (ret_var >> 3) & 0x01);
		ser_port_inst->log_add_str(ret_str);
	}
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_modem_reset(void)
{
	int ret_var = ser_port_inst->modem_reset();
	char ret_str[63];
	sprintf(ret_str, "-  door_control_modem_reset %d", ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall door_control_d2xx_dll_open(void)
{
	int ret_var = 0;
	char ret_str[63];
	ret_var = ser_port_inst->open_d2xx();
	sprintf(ret_str, "-  door_control_d2xx_dll_open %d", ret_var);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall send_ping(char * ip_addr)
{
	int ret_var = 0;
	char ret_str[63];
	ret_var = ser_port_inst->ping_addr(ip_addr, &ser_port_inst->ping_result);
	sprintf(ret_str, "- send_ping  %d", ret_var);
	printf("%s:", ret_str);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall ping_addr_add(char * ip_addr)
{
	int ret_var = 0;
	char ret_str[63];
	//cout << " ping_addr_add " << ip_addr << endl;
	//ser_port_inst->ping_addr_list.push_front((const char*)ip_addr);
	strcpy(ser_port_inst->ping_addr_char, ip_addr);
	//for (LISTSTR::iterator i =  ser_port_inst->ping_addr_list.begin(); i != ser_port_inst->ping_addr_list.end(); ++i)
	//	cout << " " << *i << endl;
	sprintf(ret_str, "- ping_addr_add  %s", ser_port_inst->ping_addr_char);
	printf("%s:", ret_str);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall ping_start()
{
	int ret_var = 0;
	char ret_str[63];
	ret_var = ser_port_inst->ping_ctrl(1);
	sprintf(ret_str, "- ping_start  %d", ret_var);
	printf("%s:", ret_str);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
__declspec(dllexport) int __stdcall ping_stop()
{
	int ret_var = 0;
	char ret_str[63];
	ret_var = ser_port_inst->ping_ctrl(0);
	sprintf(ret_str, "- ping_stop  %d", ret_var);
	printf("%s:", ret_str);
	ser_port_inst->log_add_str(ret_str);
	return ret_var;
}
